package nl.rug.snitter.message;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.NotPersistent;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;


import com.google.appengine.api.datastore.Key;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class MessageManager {
	
	@SuppressWarnings("unused")
	@PrimaryKey
	@Persistent(valueStrategy= IdGeneratorStrategy.IDENTITY)
	private Key id;
	@Persistent
	private byte[] serializedMsg= null;
	@Persistent
	private long totalMsgCount;
	@Persistent
	private byte[] serializedMsgPropagation= null;
	@NotPersistent
	private ArrayList<Long> msgIds= null;
	
	/*
	 * Used to store how a msg that was posted by an user should be sent to this user
	 */
	@NotPersistent
	private HashMap<Long, ArrayList<MessagePropagation>> msgPropagation;
	
	public MessageManager()
	{
		this.msgIds= new ArrayList<Long>();
		this.msgPropagation= new HashMap<Long, ArrayList<MessagePropagation>>();
		this.totalMsgCount= 0;
	}
	
	public int getCurrentNumberOfMessages()
	{
		return this.msgIds.size();
	}

	/**
	 * This method will return the messages made by the user.
	 * Please do not modify the array list. 
	 */
	public ArrayList<Long> getMessages()
	{
		return this.msgIds;
	}

	public long getTotalMessageCount()
	{
		return this.totalMsgCount;
	}

	public void addMessage(Long msgId)
	{
		this.msgIds.add(msgId);
		this.totalMsgCount++;
	}
	
	public void removeMsg(long msgId)
	{
//		int i;
//		for(i=0; i< this.msgId.size(); i++)
//		{
//			if(this.msgId.get(i).getMsgNumber() == number)
//			{
//				this.msg.remove(i);
//				break;
//			}
//		}
		this.msgIds.remove(msgId);
	}
	
	public void serializeFields() throws IOException
	{
		ObjectOutputStream out1= null;
		ObjectOutputStream out2= null;
		try
		{
			ByteArrayOutputStream bOut1= new ByteArrayOutputStream();
			ByteArrayOutputStream bOut2= new ByteArrayOutputStream();
			out1= new ObjectOutputStream(bOut1);
			out2= new ObjectOutputStream(bOut2);
			out1.writeObject(this.msgIds);
			out2.writeObject(this.msgPropagation);
			this.serializedMsg= bOut1.toByteArray();
			this.serializedMsgPropagation= bOut2.toByteArray();
		}
		finally
		{
			out1.close();
			out2.close();
		}
	}
	
	@SuppressWarnings("unchecked")
	public void deSerializeFields() throws IOException, ClassNotFoundException
	{
		ObjectInputStream in1= null;
		ObjectInputStream in2= null;
		try
		{
			ByteArrayInputStream bIn1= new ByteArrayInputStream(this.serializedMsg);
			ByteArrayInputStream bIn2= new ByteArrayInputStream(this.serializedMsgPropagation);
			in1= new ObjectInputStream(bIn1);
			in2= new ObjectInputStream(bIn2);
			this.msgIds= (ArrayList<Long>) in1.readObject();
			this.msgPropagation= (HashMap<Long, ArrayList<MessagePropagation>>) in2.readObject();
		}
		finally
		{
			in1.close();
			in2.close();
		}
	}
	

	public void addMsgPropagation(Long id, MessagePropagation propagation)
	{
		if(this.msgPropagation.containsKey(id))
		{
			boolean containsPropagation= false;
			if(propagation != null)
			{
				//check for duplicates
				for(MessagePropagation prog2 : this.msgPropagation.get(id))
				{
					if(prog2.getClass().getName().equals(propagation.getClass().getName()))
					{
						containsPropagation= true;
						break;
					}
				}
				if(containsPropagation == false)
				{
					this.msgPropagation.get(id).add(propagation);
				}
			}
		}
		else
		{
			ArrayList<MessagePropagation> temp= new ArrayList<MessagePropagation>();
			if(propagation != null)
			{
				temp.add(propagation);
				this.msgPropagation.put(id, temp);
			}
			else
			{
				temp.add(new SiteMessagePropagation());
				this.msgPropagation.put(id, temp);
			}
		}
	}
	

	public ArrayList<MessagePropagation> getMsgPropagation(Long id)
	{
		if(this.msgPropagation.containsKey(id))
		{
			return this.msgPropagation.get(id);
		}
		return null;
	}

//	public void removeMessagePropagation(Long id)
//	{
//		if(this.msgPropagation.containsKey(id))
//		{
//			this.msgPropagation.remove(id);
//		}
//	}

//	public void setMessagePropagation(Long id, MessagePropagation propagation)
//	{
//		if(this.msgPropagation.containsKey(id))
//		{
//			this.msgPropagation.remove(id);
//			this.msgPropagation.put(id, propagation);
//		}
}
